热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

专栏|Zabbix使用JavaScript配置Webhook发送告警通知

Wanger | Zabbix开源社区签约专家Zabbix运维工程师,熟悉Zabbix开源监控系统的架构。乐于分享Zabbix运维经验,个人公众号“运维开发故事

Wanger | Zabbix开源社区签约专家

Zabbix运维工程师,熟悉Zabbix开源监控系统的架构。乐于分享Zabbix运维经验,个人公众号“运维开发故事”。

擅长领域:Zabbix基础设施运维以及Zabbix图形化展示。

背景

Zabbix从4.4开始支持使用自定义的Javascript代码来配置Webhook媒介类型实现故障报警通知,这又为用户提供了一种使用前端代码来进行报警通知的方式。相比于在后端配置告警脚本的好处是代码可维护性更强,支持媒介类型的导入导出,省去了后端调试代码的步骤,使Zabbix更加的开箱即用。本文介绍Webhook的媒介类型是怎么配置的。

实现原理

首先看官方文档有详细介绍,Zabbix官方提供了大量的webhook媒介类型,虽然很多我们都用不上,但是我们可以参考他们的代码实现,来照葫芦画瓢编写适合我们自己的webhook媒介类型。之前我本人也看了一点点Javascript的基础,但后来看官方编写的代码和文档的时候,发现其实并不需要有多好的Javascript基础,有些代码官方又直接封装了一下,可以拿过来直接用。实现原理简单来说就是通过传入参数到Javascript代码中,Javascript会构造http请求并将传入的参数作为请求的一部分发送出去。

Zabbix封装的Javascript对象

Zabbix官方为方便我们使用Javascript的预处理和使用Webhook的媒介类型,特意在上面封装了一些对象给我们使用,同样目的也是为了能够更好的开箱即用。主要封装了两个对象。

写入zabbix日志的对象

方法描述
Log(loglevel, message)按照日志级别将写入 Zabbix 日志,日志级别可参考配置文件


例如:

Zabbix.Log(3, "this is a log entry written with 'Warning' log level")

http请求对象

官方还对http请求进行了封装,可以很方便的构造http请求。
方法描述
AddHeader(name, value)添加HTTP报头字段。此字段用于所有后续请求,直到使用ClearHeader()方法清除为止
ClearHeader()清除 HTTP 标头。如果没有设置报头字段,且发送的数据是 json 格式,默认会将 Content-Type 设置为 application/json,否则设置为 text/plain。
GetHeaders()返回接收到的 HTTP 标头字段的对象。
Get(url, data)将HTTP GET请求发送到带有可选_data_的URL,并返回响应
Put(url, data)将HTTP PUT请求发送到带有可选data的URL,并返回响应
Post(url, data)将HTTP POST请求发送到带有可选_data_的URL,并返回响应
Delete(url, data)将HTTP DELETE请求发送到带有可选data的URL,并返回响应
Status()返回最后一个HTTP请求的状态码
SetProxy(proxy)设置HTTP代理为“proxy”值。如果该参数为空,则不使用代理
官方在这里提供了一个例子来介绍如何使用封装的对象。

try {
    Zabbix.Log(4, 'jira webhook script value='+value);
 
    var result = {
        'tags': {
            'endpoint''jira'
        }
    },
    params = JSON.parse(value),
    req = new CurlHttpRequest(),
    fields = {},
    resp;
 
    req.AddHeader('Content-Type: application/json');
    req.AddHeader('Authorization: Basic '+params.authentication);
 
    fields.summary = params.summary;
    fields.description = params.description;
    fields.project = {"key": params.project_key};
    fields.issuetype = {"id": params.issue_id};
    resp = req.Post('https://tsupport.zabbix.lan/rest/api/2/issue/',
        JSON.stringify({"fields": fields})
    );
 
    if (req.Status() != 201) {
        throw 'Response code: '+req.Status();
    }
 
    resp = JSON.parse(resp);
    result.tags.issue_id = resp.id;
    result.tags.issue_key = resp.key;
} catch (error) {
    Zabbix.Log(4, 'jira issue creation failed json : '+JSON.stringify({"fields": fields}));
    Zabbix.Log(4, 'jira issue creation failed : '+error);
 
    result = {};
}
 
return JSON.stringify(result);

配置Webhook

如果我们想用官方现有的webhook媒介类型,则可以从git仓库或者源码包中下载并导入现有的xml,如果官方的webhook不能满足我们的需求则可以自己手动创建一个。webhook媒体类型的具体参数
前文说过,webhook的原理就是通过传递参数,然后对参数进行校验之后构建http请求并发送,webhook默认包含几个常用变量(URL :
, HTTPProxy:, To:{ALERT.SENDTO}, Subject:{ALERT.SUBJECT}, Message:{ALERT.MESSAGE}),传入的参数也支持问题通知中支持的所有宏,也支持使用http代理。选中Process tags_,_会讲webhook返回的json属性值作为问题事件标签。选中事件菜单复选框,可以在事件发生时点击问题名称访问外部的地址。

Webhook开发指南

官方的webhook开发指南说明点击查看。

数据验证

整个数据验证过程可以分为两部分:输入数据验证和外部系统响应数据验证。输入数据验证包括
  • Webhook 配置或 Webhook 测试中使用的值无效。
  • 缺少网络钩子参数。webhook 代码应该验证所需的参数并确定必需的参数是否存在。
  • 宏是否被解析。
输入数据验证的所有错误消息都应包含有关问题原因的信息和解决方法
响应数据验证包括
与用户输入验证一样,响应数据验证应确保来自外部系统的响应采用预期格式。这包括以下验证:
  • 是否有响应并且没有 HTTP 错误。
  • 响应是否包含预期格式的数据(原始/JSON/XML/等)。
  • 响应是否包含所有必需的字段或数据。
  • 响应数据中有没有错误。

返回值

虽然没有要求返回特定值,但在定义 webhook 的响应时应使用以下方法之一:如果 webhook 不使用标记:建议返回一个通用字符串(例如,OK
)来表示执行成功。如果 webhook 使用标签(标记Process tags复选框):webhook 应始终返回一个 JSON 对象,其中至少包含一个空对象的标签:{tags: {}}

日志记录

Webhooks 应该使用 Zabbix 提供的日志记录功能来为用户存储调试信息。应满足以下日志记录要求:
  • 应提供调试级别信息。 这可用于找出 webhook 逻辑中错误的原因。
  • 不需要在更高级别创建日志条目,因为 Zabbix 服务器会自动在“警告”(3)级别记录失败的 webhooks。
  • 日志条目应以 WEBHOOK 名称为前缀。这样是为了区分 webhook 创建的日志与和Zabbix Server 日志文件中的其他日志。
  • 无需在 WEBHOOK 的每一步都创建日志条目。

编写自定义webhook媒介类型实现发送钉钉报警通知

之前的文章已经介绍过编写脚本实现飞书的报警通知,这次将以webhook的媒介类型发送钉钉报警为例为大家介绍编写自定义的webhook媒介。

创建钉钉机器人

首先在电脑端创建自定义机器人,安全设置使用自定义关键词。


完成设置,保存好webhook,https://oapi.dingtalk.com/robot/send?access_token=e5906a9b879fe615323bd9489f46334f5539d6a46f8e29c5740ba02c7ee90e84

创建自定义报警媒介

进入报警媒介类型,选择webhook媒介类型,参数只需要填告警信息,接收人,webhook地址就可以了,脚本为:

var Dingding = {
    params: {},
    proxynull,
    setParamsfunction (params{
        if (typeof params !== 'object') {
            return;
        }
        Dingding.params = params; 
    },
    requestfunction () {
        var data = {
          msgtype"markdown",
          markdown: {
            title"报警",
            text"## 通知:\n " + Dingding.params.Message,
          },
          at: {
            atUserIds: [Dingding.params.To],
            isAtAllfalse,
          },
        },
        response,
        url = Dingding.params.URL,
        request = new HttpRequest();

        request.addHeader('Content-Type: application/json');
        if (typeof Dingding.HTTPProxy !== 'undefined' && Dingding.HTTPProxy !== '') {
            request.setProxy(Dingding.HTTPProxy);
        }

        if (typeof data !== 'undefined') {
            data = JSON.stringify(data);
        }
        Zabbix.Log(4"[Dingding Webhook] message is: " + data);
        response = request.post(url, data);

        Zabbix.log(4'[ Dingding Webhook ] Received response with status code ' +
            request.getStatus() + '\n' + response);

        if (response !== null) {
            try {
                response = JSON.parse(response);
            }
            catch (error) {
                Zabbix.log(4'[ Dingding Webhook ] Failed to parse response received from Dingding');
                response = null;
            }
        }
        
        if (request.getStatus() !== 200 || response.errcode !== 0) {
            var message = 'Request failed with status code '+request.getStatus();

            if (response !== null && typeof response.errmsg !== 'undefined') {
                message += ': 'JSON.stringify(response.errmsg) ;
            }

            throw message + '. Check debug log for more information.';
        }

        return response;
    },
};

    
try {
    var params = JSON.parse(value);
    
    if (typeof params.URL !== 'undefined' 
         && typeof params.To !== 'undefined'
         && typeof params.Message !== 'undefined') {
           Zabbix.log(4'[ Dingding Webhook ] webhookURL "' + params.URL +
                            '" sendto "'+ params.To )+'"';
        } 
        else {
          throw 'Missing parameter. URL, message, to parameter is required'
        }
    if (params.HTTPProxy) {
        Dingding.proxy = params.HTTPProxy;
    } 
    Dingding.setParams(params);
    Dingding.request();
    return 'OK';
}catch (error) {
    Zabbix.log(3'[ Dingding Webhook ] ERROR: ' + error);
    throw 'Sending failed: ' + error;
}


之后点击媒介类型后面的测试,输入参数就可以进行验证编写的自定义报警类型是否有问题。


告警消息是支持markdown的,可以将消息模板改成Markdown格式,会更好看一点。



 Zabbix5.0认证培训



7月12-16日 上海场



【客户案例】华为、中移在线、光大银行分享等

【官方博文】5.4新功能及路线图、技巧难点等

【专家专栏】周松、张思德、wanger等

Zabbix开源社区

由Zabbix大中华区唯一总代理上海宏时数据系统有限公司建立并维护,旨在提供最新资讯、交流平台和技术支持。



推荐阅读
  • 2018-2019学年第六周《Java数据结构与算法》学习总结
    本文总结了2018-2019学年第六周在《Java数据结构与算法》课程中的学习内容,重点介绍了非线性数据结构——树的相关知识及其应用。 ... [详细]
  • Python + Pytest 接口自动化测试中 Token 关联登录的实现方法
    本文将深入探讨 Python 和 Pytest 在接口自动化测试中如何实现 Token 关联登录,内容详尽、逻辑清晰,旨在帮助读者掌握这一关键技能。 ... [详细]
  • 版本控制工具——Git常用操作(下)
    本文由云+社区发表作者:工程师小熊摘要:上一集我们一起入门学习了git的基本概念和git常用的操作,包括提交和同步代码、使用分支、出现代码冲突的解决办法、紧急保存现场和恢复 ... [详细]
  • 当unique验证运到图片上传时
    2019独角兽企业重金招聘Python工程师标准model:public$imageFile;publicfunctionrules(){return[[[na ... [详细]
  • 本文介绍如何在Spring Boot项目中集成Redis,并通过具体案例展示其配置和使用方法。包括添加依赖、配置连接信息、自定义序列化方式以及实现仓储接口。 ... [详细]
  • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
  • ElasticSearch 集群监控与优化
    本文详细介绍了如何有效地监控 ElasticSearch 集群,涵盖了关键性能指标、集群健康状况、统计信息以及内存和垃圾回收的监控方法。 ... [详细]
  • SpringMVC RestTemplate的几种请求调用(转)
    SpringMVCRestTemplate的几种请求调用(转),Go语言社区,Golang程序员人脉社 ... [详细]
  • Django Token 认证详解与 HTTP 401、403 状态码的区别
    本文详细介绍了如何在 Django 中配置和使用 Token 认证,并解释了 HTTP 401 和 HTTP 403 状态码的区别。通过具体的代码示例,帮助开发者理解认证机制及权限控制。 ... [详细]
  • 本文档汇总了Python编程的基础与高级面试题目,涵盖语言特性、数据结构、算法以及Web开发等多个方面,旨在帮助开发者全面掌握Python核心知识。 ... [详细]
  • 本文深入探讨了 PHP 实现计划任务的方法,包括其原理、具体实现方式以及在不同操作系统中的应用。通过详细示例和代码片段,帮助开发者理解和掌握如何高效地设置和管理定时任务。 ... [详细]
  • 探讨在使用 Fast-Android-Networking 库时遇到的 addStringBody 方法无法正常工作的问题及其解决方案。 ... [详细]
  • 基于Node.js、Express、MongoDB和Socket.io的实时聊天应用开发
    本文详细介绍了使用Node.js、Express、MongoDB和Socket.io构建的实时聊天应用程序。涵盖项目结构、技术栈选择及关键依赖项的配置。 ... [详细]
  • 本文介绍了在Java环境中使用PDFBox和XPDF工具从PDF文件中提取文本内容的方法。重点讨论了处理中文字符集及解决相关错误的技术细节,特别是针对某些特定格式的PDF文件(如网上填写的报名表和下载的论文)遇到的问题及解决方案。 ... [详细]
  • MongoDB的核心特性与架构解析
    本文深入探讨了MongoDB的核心特性,包括其强大的查询语言、灵活的文档模型以及高效的索引机制。此外,还详细介绍了MongoDB的体系结构,解释了其文档、集合和数据库的层次关系,并对比了MongoDB与传统关系型数据库(如MySQL)的逻辑结构。 ... [详细]
author-avatar
Damon777
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有